#pragma once
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstring>
#include <strings.h>
#include <poll.h>
#include "Log.hpp"

const int num = 1;

class PollServer
{

public:
    PollServer(uint16_t port) : _port(port), _isrunning(false), _listensock(-1), _rfds(nullptr), _num(num)
    {
    }

    void Init(int backlog)
    {
        // 创建监听sock
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensock < 0)
        {
            LOG(Abnormal, "create listen sock error\n");
            exit(1);
        }
        int opt = 1;
        setsockopt(_listensock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
        struct sockaddr_in addr;
        bzero(&addr, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(_port);
        addr.sin_addr.s_addr = INADDR_ANY;
        int n = bind(_listensock, (struct sockaddr *)(&addr), sizeof(addr));
        if (n < 0)
        {
            LOG(Abnormal, "bind listen sock error\n");
            exit(1);
        }

        n = listen(_listensock, backlog);
        if (n < 0)
        {
            LOG(Abnormal, "listen listen sock error\n");
            exit(1);
        }

        _rfds = new struct pollfd[_num];
        // 初始化rfds
        for (int i = 0; i < num; i++)
        {
            _rfds[i].fd = -1;
            _rfds[i].events = 0;
            _rfds[i].revents = 0;
        }
        _rfds[0].fd = _listensock;
        _rfds[0].events = POLLIN;
    }

    bool AddSock(int fd)
    {
        int pos = 0;
        for (; pos < _num; pos++)
        {
            if (_rfds[pos].fd == -1)
            {
                _rfds[pos].fd = fd;
                _rfds[pos].events = POLLIN;
                LOG(Info, "add sock seccuss, %d\n", fd);
                return true;
            }
        }
        return false;
    }

    bool ReallocRfds()
    {
        struct pollfd *tmp = new struct pollfd[_num * 2];
        if(tmp == nullptr)
        {
            LOG(Debug, "tmp is nullptr\n");
            return false;
        }
        for (int i = 0; i < _num * 2; i++)
        {
            tmp[i].fd = -1;
            tmp[i].events = 0;
            tmp[i].revents = 0;
        }
        memcpy(tmp, _rfds, sizeof(struct pollfd) * _num);
        delete []_rfds;
        _rfds = tmp;
        _num *= 2;
        LOG(Info, "realloc _rfds seccuss, size: %d\n", _num);
        return true;
    }

    void ReadHandler()
    {
        // LOG(Debug, "读条件就绪\n");
        for (int i = 0; i < _num; i++)
        {
            int fd = _rfds[i].fd;
            int revents = _rfds[i].revents;
            if (fd != -1 && revents & POLLIN) // 读条件就绪
            {
                if (_listensock == fd)
                {
                    // 有新的文件描述符到来
                    struct sockaddr_in addr;
                    socklen_t len = sizeof(addr);
                    int newsock = accept(_listensock, (struct sockaddr *)(&addr), &len);
                    if (newsock < 0)
                    {
                        // 获取连接失败，继续循环检测其他文件描述符
                        LOG(Abnormal, "connection establishment failed\n");
                        continue;
                    }

                    if (!AddSock(newsock))
                    {
                        // poll承受的文件描述符已满，扩容
                        if(!ReallocRfds())
                        {
                            LOG(Abnormal, "realloc _rfds error, add sock fail\n");
                            close(newsock);
                            continue;
                        }
                        AddSock(newsock);
                    }
                }
                else
                {
                    char buffer[1024];
                    int n = read(fd, buffer, sizeof(buffer) - 1);
                    if (n > 0)
                    {
                        buffer[n] = 0;
                        std::cout << "client say# " << buffer << endl;
                    }
                    else
                    {
                        close(fd);
                        _rfds[i].fd = -1;
                        _rfds[i].events = 0;
                        _rfds[i].revents = 0;
                    }
                }
            }
        }
    }

    void Loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            int timeout = 1000;

            int n = poll(_rfds, _num, timeout);
            switch (n)
            {
            case 0:
                LOG(Info, "read condition not ready\n");
                break;
            case -1:
                break;
            default:
                ReadHandler();
                break;
            }
            PrintBug();
        }
        _isrunning = false;
    }

    void PrintBug()
    {
        std::cout << "conn list: ";
        for (int i = 0; i < _num; i++)
        {
            if (_rfds[i].fd != -1)
            {
                std::cout << _rfds[i].fd << " ";
            }
        }
        std::cout << std::endl;
    }

    ~PollServer()
    {
        delete[] _rfds;
    }

private:
    uint16_t _port;
    int _listensock;
    bool _isrunning;

    int _num;
    struct pollfd *_rfds;
};
